//
// Created by Administrator on 2021/4/26.
//

/*
传送带上的包裹必须在 D 天内从一个港口运送到另一个港口。

传送带上的第 i个包裹的重量为weights[i]。每一天，我们都会按给出重量的顺序往传送带上装载包裹。我们装载的重量不会超过船的最大运载重量。

返回能在 D 天内将传送带上的所有包裹送达的船的最低运载能力。


示例 1：
输入：weights = [1,2,3,4,5,6,7,8,9,10], D = 5
输出：15
解释：
船舶最低载重 15 就能够在 5 天内送达所有包裹，如下所示：
第 1 天：1, 2, 3, 4, 5
第 2 天：6, 7
第 3 天：8
第 4 天：9
第 5 天：10

请注意，货物必须按照给定的顺序装运，因此使用载重能力为 14 的船舶并将包装分成 (2, 3, 4, 5), (1, 6, 7), (8), (9), (10) 是不允许的。

示例 2：
输入：weights = [3,2,2,4,1,4], D = 3
输出：6
解释：
船舶最低载重 6 就能够在 3 天内送达所有包裹，如下所示：
第 1 天：3, 2
第 2 天：2, 4
第 3 天：1, 4

示例 3：
输入：weights = [1,2,3,1,1], D = 4
输出：3
解释：
第 1 天：1
第 2 天：2
第 3 天：3
第 4 天：1, 1


提示：

1 <= D <= weights.length <= 50000
1 <= weights[i] <= 500

来源：力扣（LeetCode）
链接：https://leetcode-cn.com/problems/capacity-to-ship-packages-within-d-days
著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。*/
#include <vector>
#include <algorithm>
#include <numeric>
#include <iostream>

class Solution {
public:
    int shipWithinDays(std::vector<int> &weights, int D) {
        /**找到一个D的下界
         * 二分查找
         * 左边界：最重的货物重量
         * 右边界：货物重量总和
         * **/
        int lhs = *std::max_element(weights.begin(), weights.end());
        int rhs = std::accumulate(weights.begin(), weights.end(), 0);
        while (lhs <= rhs) {
            // need是需要的天数
            // cur是当天的货物量
            int need = 1, cur = 0;
            int mid = lhs + (rhs - lhs) / 2;
            for (int weight:weights) {
                // 超重，放到第二天
                if (weight + cur > mid) {
                    ++need;
                    cur = 0;
                }
                cur += weight;
            }
            // 需要的天数小于D
            if (need <= D) rhs = mid-1;
            else lhs = mid + 1;
        }
        return lhs;
    }
};

int main() {
    Solution sol;
    std::vector<int> v1{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    std::cout << sol.shipWithinDays(v1, 5) << std::endl;
    std::vector<int> v2{3, 2, 2, 4, 1, 4};
    std::cout << sol.shipWithinDays(v2, 3) << std::endl;
    std::vector<int> v3{1, 2, 3, 1, 1};
    std::cout << sol.shipWithinDays(v3, 4) << std::endl;
    return 0;
}